package com.ajocer.springbootinit.websocket;

import com.alibaba.fastjson.JSON;
import com.ajocer.springbootinit.rag.MultiLayerCacheService;
import com.ajocer.springbootinit.rag.TourismRagService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 旅游推荐WebSocket服务
 * 提供实时旅游推荐功能
 */
@Controller
@Slf4j
public class TourismWebSocketService {

    @Autowired
    private SimpMessagingTemplate messagingTemplate;

    @Autowired
    private TourismRagService tourismRagService;
    
    @Autowired
    private MultiLayerCacheService cacheService;
    
    // 存储进行中的请求
    private final Map<String, Boolean> processingRequests = new ConcurrentHashMap<>();

    /**
     * 处理景点推荐请求
     * @param request 推荐请求
     */
    @MessageMapping("/recommend/spots")
    public void recommendSpots(@Payload RecommendRequest request) {
        String requestId = UUID.randomUUID().toString();
        String userId = request.getUserId();
        String userPreference = request.getPreference();
        
        log.info("收到景点推荐WebSocket请求: userId={}, preference={}", userId, userPreference);
        
        // 发送处理中消息
        sendProcessingMessage(userId, requestId, "spots");
        
        // 异步处理推荐请求
        CompletableFuture.runAsync(() -> {
            try {
                processingRequests.put(requestId, true);
                String result;
                
                // 检查缓存中是否有结果
                String cacheKey = "spots:" + userPreference;
                boolean isCached = false;
                try {
                    isCached = cacheService.hasCache(cacheKey);
                } catch (Exception e) {
                    log.error("检查缓存失败", e);
                }

                if (isCached) {
                    sendProgressMessage(userId, requestId, "spots", 50, "正在从缓存获取推荐结果...");
                    // 从缓存获取结果
                    result = cacheService.getRecommendationCache(cacheKey, () -> null);
                } else {
                    // 发送进度消息
                    sendProgressMessage(userId, requestId, "spots", 20, "正在分析您的偏好...");
                    Thread.sleep(500); // 模拟处理时间
                    
                    sendProgressMessage(userId, requestId, "spots", 40, "正在检索相关景点...");
                    Thread.sleep(500); // 模拟处理时间
                    
                    // 使用RAG服务生成推荐结果
                    result = tourismRagService.recommendRoutes(userPreference);
                }
                
                // 发送结果
                sendResultMessage(userId, requestId, "spots", result);
                
            } catch (Exception e) {
                log.error("处理景点推荐请求失败", e);
                sendErrorMessage(userId, requestId, "spots", "推荐失败，请稍后再试");
            } finally {
                processingRequests.remove(requestId);
            }
        });
    }
    
    /**
     * 处理路线推荐请求
     * @param request 推荐请求
     */
    @MessageMapping("/recommend/routes")
    public void recommendRoutes(@Payload RecommendRequest request) {
        String requestId = UUID.randomUUID().toString();
        String userId = request.getUserId();
        String userPreference = request.getPreference();
        
        log.info("收到路线推荐WebSocket请求: userId={}, preference={}", userId, userPreference);
        
        // 发送处理中消息
        sendProcessingMessage(userId, requestId, "routes");
        
        // 异步处理推荐请求
        CompletableFuture.runAsync(() -> {
            try {
                processingRequests.put(requestId, true);
                String result;
                
                // 检查缓存中是否有结果
                String cacheKey = "routes:" + userPreference;
                boolean isCached = false;
                try {
                    isCached = cacheService.hasCache(cacheKey);
                } catch (Exception e) {
                    log.error("检查缓存失败", e);
                }

                if (isCached) {
                    sendProgressMessage(userId, requestId, "routes", 50, "正在从缓存获取推荐结果...");
                    // 从缓存获取结果
                    result = cacheService.getRecommendationCache(cacheKey, () -> null);
                } else {
                    // 发送进度消息
                    sendProgressMessage(userId, requestId, "routes", 20, "正在分析您的偏好...");
                    Thread.sleep(500); // 模拟处理时间
                    
                    sendProgressMessage(userId, requestId, "routes", 40, "正在检索相关路线...");
                    Thread.sleep(500); // 模拟处理时间
                    
                    // 使用RAG服务生成推荐结果
                    result = tourismRagService.recommendRoutes(userPreference);
                }
                
                // 发送结果
                sendResultMessage(userId, requestId, "routes", result);
                
            } catch (Exception e) {
                log.error("处理路线推荐请求失败", e);
                sendErrorMessage(userId, requestId, "routes", "推荐失败，请稍后再试");
            } finally {
                processingRequests.remove(requestId);
            }
        });
    }
    
    /**
     * 发送处理中消息
     */
    private void sendProcessingMessage(String userId, String requestId, String type) {
        Map<String, Object> message = new HashMap<>();
        message.put("type", "processing");
        message.put("requestId", requestId);
        message.put("recommendType", type);
        message.put("timestamp", System.currentTimeMillis());
        
        messagingTemplate.convertAndSendToUser(userId, "/queue/recommend", JSON.toJSONString(message));
    }
    
    /**
     * 发送进度消息
     */
    private void sendProgressMessage(String userId, String requestId, String type, int progress, String status) {
        Map<String, Object> message = new HashMap<>();
        message.put("type", "progress");
        message.put("requestId", requestId);
        message.put("recommendType", type);
        message.put("progress", progress);
        message.put("status", status);
        message.put("timestamp", System.currentTimeMillis());
        
        messagingTemplate.convertAndSendToUser(userId, "/queue/recommend", JSON.toJSONString(message));
    }
    
    /**
     * 发送结果消息
     */
    private void sendResultMessage(String userId, String requestId, String type, String result) {
        Map<String, Object> message = new HashMap<>();
        message.put("type", "result");
        message.put("requestId", requestId);
        message.put("recommendType", type);
        message.put("result", result);
        message.put("timestamp", System.currentTimeMillis());
        
        messagingTemplate.convertAndSendToUser(userId, "/queue/recommend", JSON.toJSONString(message));
    }
    
    /**
     * 发送错误消息
     */
    private void sendErrorMessage(String userId, String requestId, String type, String errorMessage) {
        Map<String, Object> message = new HashMap<>();
        message.put("type", "error");
        message.put("requestId", requestId);
        message.put("recommendType", type);
        message.put("error", errorMessage);
        message.put("timestamp", System.currentTimeMillis());
        
        messagingTemplate.convertAndSendToUser(userId, "/queue/recommend", JSON.toJSONString(message));
    }
    
    /**
     * 推荐请求类
     */
    public static class RecommendRequest {
        private String userId;
        private String preference;
        
        public String getUserId() {
            return userId;
        }
        
        public void setUserId(String userId) {
            this.userId = userId;
        }
        
        public String getPreference() {
            return preference;
        }
        
        public void setPreference(String preference) {
            this.preference = preference;
        }
    }
} 